/*
 * CustomizedFieldPlugin
 * This Plug-in used in CustomizedLayout for customizing markInvalid, clearInvalid when server responses JSON that has errors. 
 */
CustomizedFieldPlugin = Ext.extend(Ext.util.Observable, {
    constructor : function(config){
        config = config || {};
        
        Ext.apply(this, config);
        CustomizedFieldPlugin.superclass.constructor.call(this);
    },
    
    /**
     * @override from Ext.form.Field
     * This function will override the default markInvalid of Field.
     * It will high light the label, unit, errorMessage and change border color of Field to red.
     * @param {Mixed} fieldError , for example {id : 'pid', action : 'error', msg : 'This field is unique'} 
     */
    markInvalid : function(fieldError) {
        if (this.rendered) {
            var action = fieldError.action;
            if (fieldError.msg) {
                this.errorEl.update(fieldError.msg);
            }
            if(action != this.icon) {
                var fieldCls = 'customized-field-' + action;
                var labelCls = 'customized-field-label-' + action
                this.el.addClass(fieldCls);
                this.itemCt.addClass(labelCls);
                this.changeState(action);
            }
            
            //Disable icon's ToolTip when its state is error
            if(this.iconToolTip && action === 'error') {
                this.iconToolTip.disable();
            }
        }
        
        this.setActiveError(fieldError.msg);
    }, 
    
    /**
     * @override from Ext.form.Field
     * This function will override the default markInvalid of Field.
     */
    clearInvalid : function(){
        if (this.rendered) {
            if(this.previousState) {
                this.errorEl.update('');
                //Enable icon's ToolTip when previous state is hint
                if(this.iconToolTip && this.previousState == 'hint') {
                    this.iconToolTip.enable();
                }
                //Remove current sate 
                var fieldCls = 'customized-field-' + this.icon;
                var labelCls = 'customized-field-label-' + this.icon;
                if (this.el.hasClass(fieldCls)) {
                    this.el.removeClass(fieldCls);
                }
                this.itemCt.removeClass(labelCls);
                //Apply previous state 
                var fieldCls = 'customized-field-' + this.previousState;
                var labelCls = 'customized-field-label-' + this.previousState;
                this.changeState(this.previousState);
                delete this.previousState;
            }
        }
        this.unsetActiveError();
    },
    
    /**
     * Uses getErrors to build an array of validation errors. If any errors are found, markInvalid is called
     * with the first and false is returned, otherwise true is returned. Previously, subclasses were invited
     * to provide an implementation of this to process validations - from 3.2 onwards getErrors should be
     * overridden instead.
     * @param {Mixed} The current value of the field
     * @return {Boolean} True if all validations passed, false if one or more failed
     */
    validateValue : function(value) {
        //currently, we only show 1 error at a time for a field, so just use the first one
        var error = this.getErrors(value)[0];

        if (error == undefined) {
           return true;
       }
       else {
           var fieldError = {
               id : this.id || this.name, action : this.action ? this.action : 'error', msg : error
           };
           if (this.ownerCt.hasLayout) {
               this.markInvalid(fieldError);
           }
           else if (!(this instanceof Ext.ux.NumericField)){
               this.ownerCt.on('afterlayout', function() {
                   this.markInvalid(fieldError);
               }, this);
           }

           return false;
       }
    },
    
    /**
     * @private
     * Apply new state for icon node and store the current state to a memory which is called previous state.
     */
    changeState : function(newState) {
        this.previousState = this.icon;
        var iconCls = 'customizedlayout-icon-' + this.icon;
        if(this.errorIcon && this.errorIcon.hasClass(iconCls)) {
            this.errorIcon.removeClass(iconCls);
            iconCls = 'customizedlayout-icon-' + newState;
            this.errorIcon.addClass(iconCls);
        }
        this.icon = newState;
    },
    
    hideValue : function(){
        if(this instanceof Ext.form.ComboBox){
            this.disabledClass = 'customized-combobox-field-hidden';
            this.disable();
        }
    },
    
    init : function(field){
        this.field = field;

        if(false == (field instanceof Ext.form.Field)) {
            return;
        }
        
        // By default, don't validate data on blur and keyup.
        
        // This will prevent validate after blur
        field.validateOnBlur = false
        // This will prevent validate after keyup
        field.validationEvent = false
        
        // Catch to more processing afterRender 
        // In case of readOnly/infoLabel fields:
        // Each field must have the separate plugins to make afterMethod work correctly
        // Because if we use the same plugin for all fields, only the last one get doAfterRender processed.
        field.afterMethod('afterRender', this.doAfterRender, this);
        // Apply margin/padding globally
        if(field.applyMarginGlobally == true){
            field.anchor = '95%';
        }
        
        Ext.apply(field, {
            'markInvalid' : this.markInvalid,
            'clearInvalid' : this.clearInvalid,
            'validateValue' : this.validateValue,
            'changeState' : this.changeState,
            'hideValue' : this.hideValue
        });
    },
    
    /**
     * Apply oxygen read-only style for all form fields in oxyc.
     */
    doAfterRender : function(){
       //Show info label if needed
       if(this.field.infoLabelText){
           this.field.ownerCt.on('afterlayout', function(){
               this.updateInfoLabel(this.field.initialConfig.infoLabelText);
           }, this);
       }
    },

    updateInfoLabel : function(infoLabel) {
      if (this.field.infoLabel) {
          this.field.infoLabel.dom.innerHTML = infoLabel;
      }
    }
});

